/**
 * 
 */
package fr.cie.blog.controller;

import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;

import com.opensymphony.xwork2.ActionContext;

import fr.cie.blog.beans.Avatar;
import fr.cie.blog.beans.Card;
import fr.cie.blog.beans.Country;
import fr.cie.blog.beans.Interest;
import fr.cie.blog.beans.Style;
import fr.cie.blog.beans.User;
import fr.cie.blog.domainservice.IServiceAvatar;
import fr.cie.blog.domainservice.IServiceCard;
import fr.cie.blog.domainservice.IServiceCountry;
import fr.cie.blog.domainservice.IServiceInterest;
import fr.cie.blog.domainservice.IServiceStyle;
import fr.cie.blog.domainservice.IServiceUser;

/**
 * @author Jee3
 * 
 */
public class UserAction extends GenericAction {

	/**
	 * serialVersionUID.
	 */
	private static final long serialVersionUID = -4214733843511464331L;

	/**
	 * Log4J the logger.
	 */
	private static final Logger LOG = Logger.getLogger(UserAction.class);

	/**
	 * serviceUser.
	 */
	private final IServiceUser serviceUser;

	/**
	 * serviceUser.
	 */
	private final IServiceStyle serviceStyle;

	/**
	 * serviceCard.
	 */
	private final IServiceCard serviceCard;

	/**
	 * serviceCard.
	 */
	private final IServiceAvatar serviceAvatar;

	/**
	 * serviceInterest.
	 */
	private final IServiceInterest serviceInterest;

	/**
	 * serviceCountry.
	 */
	private final IServiceCountry serviceCountry;

	/**
	 * user.
	 */
	private User user;

	/**
	 * userList.
	 */
	private List<User> userList;

	/**
	 * the secondary password to verify.
	 */
	private String passwordCheck;

	/**
	 * Interest List.
	 */
	private List<Integer> interestIDList;

	/**
	 * @param pServiceUser
	 *            serviceUser
	 * @param pServiceStyle
	 *            serviceStyle
	 * @param pServiceCard
	 *            serviceCard
	 * @param pServiceAvatar
	 *            serviceAvatar
	 * @param pServiceInterest
	 *            serviceInterest
	 * @param pServiceCountry
	 *            serviceCOuntry
	 */
	public UserAction(final IServiceUser pServiceUser,
			final IServiceStyle pServiceStyle,
			final IServiceCard pServiceCard,
			final IServiceAvatar pServiceAvatar,
			final IServiceInterest pServiceInterest,
			final IServiceCountry pServiceCountry) {
		super();
		serviceUser = pServiceUser;
		serviceStyle = pServiceStyle;
		serviceCard = pServiceCard;
		serviceAvatar = pServiceAvatar;
		serviceInterest = pServiceInterest;
		serviceCountry = pServiceCountry;
	}

	/**
	 * @return the user
	 */
	public final User getUser() {
		return user;
	}

	/**
	 * @return the userList
	 */
	public final List<User> getUserList() {
		return userList;
	}

	/**
	 * @param pUser
	 *            the user to set
	 */
	public final void setUser(final User pUser) {
		this.user = pUser;
	}

	/**
	 * @param pUserList
	 *            the userList to set
	 */
	public final void setUserList(final List<User> pUserList) {
		this.userList = pUserList;
	}

	/**
	 * @return the passwordCheck
	 */
	public final String getPasswordCheck() {
		return passwordCheck;
	}

	/**
	 * @param pPasswordCheck
	 *            the passwordCheck to set
	 */
	public final void setPasswordCheck(final String pPasswordCheck) {
		this.passwordCheck = pPasswordCheck;
	}

	/**
	 * @return the List of Interest
	 */
	public final List<Integer> getInterestIDList() {
		return interestIDList;
	}

	/**
	 * @param pInterestIDList
	 *            the interestList to set
	 */
	public final void setInterestIDList(final List<Integer> pInterestIDList) {
		interestIDList = pInterestIDList;
	}

	/**
	 * @return SUCCESS
	 */
	public final String listUsers() {
		return "";
	}

	/**
	 * Compare the form [login, password] to the base. It brings back the user
	 * if the connection succeed.
	 * 
	 * @return @struts ERROR or SUCCESS
	 */
	public final String login() {

		LOG.info("MB - ENTERING IN login(): " + user.getLogin());
		String message;
		// on créé un nouveau modèle
		// on interroge le modèle
		final User userBase = serviceUser.authenticateUser(user.getLogin(),
				user.getPassword());

		// TODO: possibilité de catcher une exception à la place des tests
		// métiers.
		// test métier si l'identification est ok
		if (userBase == null) {
			addActionMessage("Error login ? user lost ? pwd forgotten ?");
			message = ERROR;
		} else {
			// on récupère la session courante
			setSession(ActionContext.getContext().getSession());
			// on renseigne la session
			user = userBase;
			getSession().put("user", user);
			LOG.info("connection succeed, enjoy :)");
			message = SUCCESS;
		}
		return message;
	}

	/**
	 * @return SUCCESS
	 */
	public final String logout() {
		// on récupère la session courante
		setSession(ActionContext.getContext().getSession());

		// on génère un utilisateur par défaut
		final User userBase = new User();

		// on désinscrit l'utilisateur de la session en le remplaçant par un
		// utilisateur par défaut
		getSession().put("user", userBase);
		LOG.info("disconnection succeed, enjoy :)");

		return SUCCESS;
	}

	/**
	 * the User to modify its role.
	 * 
	 * @return SUCCESS
	 */
	public final String modifyRole() {
		serviceUser.update(user);
		return SUCCESS;
	}

	/**
	 * @return SUCCESS
	 */
	public final String readBlog() {
		LOG.info("MB - ENTERING IN readBlog() no parameter");
		return SUCCESS;
	}

	/**
	 * Register a new user with informations.
	 * 
	 * @return SUCCESS
	 */
	public final String register() {

		LOG.info("MB - ENTERING IN register(): " + user.getLogin());

		String message;

		final User userBase = serviceUser.findByLogin(user.getLogin());
		if (userBase == null) {

			// Save user's main attributes
			user.setRole(1);
			serviceUser.save(user);

			// ===== Card management =====
			final Card card = user.getCard();

			// Re-attach current style to persistence layer
			final Style style = (Style) getSession().get("currentStyle");
			serviceStyle.save(style);

			// Re-attach chosen avatar to persistence layer
			Country country;
			if (card.getCountry() == null) {
				// default country
				country = serviceCountry.findById(1);
			} else {
				country = serviceCountry.findById(card.getCountry().getId());
			}

			// Avatar management
			// Get the filename from session (fugit)
			final String avatarFileName = (String) ActionContext.getContext()
					.getSession().get("fileName");
			// Try to get avatar from DB
			Avatar avatar = serviceAvatar.findByName(avatarFileName);

			if (avatarFileName == null && avatar == null) {
				// No avatar uploaded and does not exists => default avatar
				avatar = serviceAvatar.findById(1);
			} else if (avatar == null) {
				// Does not exists in DB => Save new avatar
				avatar = new Avatar();
				avatar.setPath("uploads/" + avatarFileName);
				avatar.setName(avatarFileName);
				serviceAvatar.save(avatar);
			}
			// Delete the key "fileName" from Session
			ActionContext.getContext().getSession().remove("fileName");

			// ==== links between card and other information === //

			// Re-attach interestList to persistence layer and add to card
			final List<Interest> interestList = new ArrayList<Interest>();
			for (int interestID : interestIDList) {
				interestList.add(serviceInterest.findById(interestID));
			}

			// Save basic information without relations
			card.setAvatar(null);
			card.setCountry(null);
			card.setInterestList(null);
			card.setStyle(null);
			card.setOwner(null);
			serviceCard.save(card);

			// Update all relations mentioned in selected card
			card.setInterestList(interestList);
			card.setOwner(user);
			card.setStyle(style);
			card.setCountry(country);
			card.setAvatar(avatar);
			serviceCard.update(card);

			message = SUCCESS;
		} else {
			// WARN : login is already chosen (exception ?)
			message = INPUT;
			LOG.error("login is already chosen");
		}

		return message;
	}

	/**
	 * 
	 * @return SUCCESS
	 */
	public final String registrationForm() {

		return SUCCESS;
	}
}
